﻿//
//Based on work by fiftypence in Doctrine CC (BT beta build)
//

using System;
using System.Collections.Generic;
using System.Linq;

using Styx;

using Styx.CommonBot;
using Styx.CommonBot.Inventory;
using Styx.CommonBot.Routines;
using Styx.Helpers;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWObjects;

using Styx.TreeSharp;
using Action = Styx.TreeSharp.Action;
using Styx.Common;



namespace Crusader
{
    partial class Routine : CombatRoutine
    {

        #region Helpers from Doctrine Early BT release by fiftypence

        //******************************************************************************************
        //* The following helpers may be reused at will, as long as credit is given to fiftypence. *
        //******************************************************************************************

        #region Non-BT Helpers

        /// <summary>
        ///     List of nearby enemy units that pass certain criteria, this list should only return units 
        ///     in active combat with the player, the player's party, or the player's raid.
        /// </summary>

        public static List<WoWUnit> EnemyUnits
        {
            get
            {
                return
                    NearbyUnitsInCombatWithMe.Where(u => u.Distance <= Crusader.Settings.Instance.AoERange).ToList();
                    //UnfriendlyUnitsNearTarget(Crusader.Settings.Instance.AoERange).ToList();
            }
        }

        #region Taken from Singular.
        /// <summary>
        ///   Gets the nearby unfriendly units within 40 yards.
        /// </summary>
        /// <value>The nearby unfriendly units.</value>
        public static IEnumerable<WoWUnit> NearbyUnfriendlyUnits
        {
            get { return ObjectManager.GetObjectsOfType<WoWUnit>(false, false).Where(p => ValidUnit(p) && p.DistanceSqr <= 40 * 40).ToList(); }
        }

        /// <summary>
        ///   Gets the nearby friendly units within 40 yards.
        /// </summary>
        /// <value>The nearby friendly units. Party/Raid else all.</value>
        public static IEnumerable<WoWUnit> NearbyFriendlyUnits
        {
            get {
                if (Me.GroupInfo.IsInRaid)
                    return Me.RaidMembers.Where(p => p.IsFriendly && p.IsAlive && p.DistanceSqr <= 40 * 40).ToList();
                else if(Me.GroupInfo.IsInParty)
                    return Me.PartyMembers.Where(p => p.IsFriendly && p.IsAlive && p.DistanceSqr <= 40 * 40).ToList();
                else
                    return ObjectManager.GetObjectsOfType<WoWUnit>(false, false).Where(p => p.IsFriendly && p.DistanceSqr <= 40 * 40).ToList();
            
            }
        }

        public static IEnumerable<WoWUnit> NearbyUnitsInCombatWithMe
        {
            get { return ObjectManager.GetObjectsOfType<WoWUnit>(false, false).Where(p => ValidUnit(p) && p.DistanceSqr <= 40 * 40 && CombatWithMe(p)).ToList(); }
        }

        static bool CombatWithMe(WoWUnit p)
        {
            return p.Combat;
        }

        static bool ValidUnit(WoWUnit p)
        {

            // Ignore shit we can't select/attack
            if (!p.CanSelect || !p.Attackable)
                return false;

            if (p.Name.Contains("Training Dummy"))
                return true;

            // Ignore friendlies!
            if (p.IsFriendly)
                return false;

            // Duh
            if (!p.IsAlive)
                return false;

            // If its a pet, lets ignore it please.
            if (p.IsPet || p.OwnedByRoot != null)
                return false;

            // And ignore critters/non-combat pets
            if (p.IsNonCombatPet || p.IsCritter)
                return false;

            return true;
        }

        /// <summary>
        ///   Gets the nearby unfriendly units within *distance* yards.
        /// </summary>
        /// <param name="distance"> The distance to check from current target</param>
        /// <value>The nearby unfriendly units.</value>
        public static IEnumerable<WoWUnit> UnfriendlyUnitsNearTarget(float distance)
        {
            var dist = distance * distance;
            var curTarLocation = StyxWoW.Me.CurrentTarget.Location;
            return ObjectManager.GetObjectsOfType<WoWUnit>(false, false).Where(
                        p => ValidUnit(p) && p.Location.DistanceSqr(curTarLocation) <= dist).ToList();
        }

        public static Composite CastOnGround(string spell, LocationRetriever onLocation, SimpleBooleanDelegate requirements)
        {
            return new Decorator(
                ret => requirements(ret) && SpellManager.CanCast(spell),

                new Sequence(
                    new Action(ret => Logging.Write("[{0}] {1} @Target", CurrentHolyPower(), spell, ((WoWPoint)onLocation(ret)))),
                    new Action(ret => SpellManager.Cast(spell)),
                    new WaitContinue(1,
                                    ret =>
                                    StyxWoW.Me.CurrentPendingCursorSpell != null, new CommonBehaviors.Actions.ActionAlwaysSucceed()),
                    new Action(ret => SpellManager.ClickRemoteLocation(onLocation(ret)))
                ));
                
        }

        public delegate WoWPoint LocationRetriever(object context);
        public delegate bool SimpleBooleanDelegate(object context);


        #endregion


        /// <summary>
        ///     Checks to see if specified target is under the effect of crowd control
        /// </summary>
        /// <param name="target">Target</param>
        /// <returns></returns>

        public static bool IsCrowdControlled(WoWUnit target)
        {
            // Just want to throw a shout-out to Singular for this function.
            return target.GetAllAuras().Count(
            unit => unit.Spell.Mechanic == WoWSpellMechanic.Banished
                || unit.Spell.Mechanic == WoWSpellMechanic.Charmed
                || unit.Spell.Mechanic == WoWSpellMechanic.Horrified
                || unit.Spell.Mechanic == WoWSpellMechanic.Incapacitated
                || unit.Spell.Mechanic == WoWSpellMechanic.Polymorphed
                || unit.Spell.Mechanic == WoWSpellMechanic.Sapped
                || unit.Spell.Mechanic == WoWSpellMechanic.Shackled
                || unit.Spell.Mechanic == WoWSpellMechanic.Asleep
                || unit.Spell.Mechanic == WoWSpellMechanic.Frozen
            ) > 0;
        }

        /// <summary>
        ///     Returns the lowest threat enemy nearby who is not crowd controlled
        /// </summary>
        /// <param name="target">Target</param>
        /// <returns></returns>

        private WoWUnit LowestThreat()
        {
            return Me.CurrentTarget;
        }

        /// <summary>
        ///     Checks to see if any nearby units are under breakable crowd control.
        /// </summary>

        public static bool ShouldWeAoe()
        {
            foreach (WoWUnit unit in EnemyUnits)
            {
                if (IsCrowdControlled(unit))
                {
                    return false;
                }
            }

            return true;
        }

        /// <summary>
        ///     Checks to see if any tauntable units are nearby, and if they 
        ///     require taunting
        /// </summary>

        public static bool ShouldWeTaunt()
        {
            return false;
        }

        /// <summary>
        ///     Check if player has specified active buff using Lua.
        /// </summary>
        /// <param name="BuffName"></param>

        public static bool PlayerHasBuff(string BuffName)
        {
            /*
            string BuffNameLua = Lua.GetReturnValues(string.Format("local name = UnitBuff(\"player\", \"{0}\"); " +
                                                 "return name", BuffName))[0];

            if (BuffNameLua == BuffName) return true;
            else return false; */

            return 0 < PlayerBuffTimeLeft(BuffName);

        }

        public static bool UnitHasAura(WoWUnit unit, string aura, int stacks, WoWUnit creator)
        {
            return unit.GetAllAuras().Any(a => a.Name == aura && a.StackCount >= stacks &&
                                              (creator == null || a.CreatorGuid == creator.Guid));
        }

        public static int UnitHasAuraDuration(WoWUnit unit, string aura, int stacks, WoWUnit creator)
        {
            return unit.GetAllAuras().First(a => a.Name == aura && a.StackCount >= stacks &&
                (creator == null || a.CreatorGuid == creator.Guid)).TimeLeft.Seconds;
        }

        /// <summary>
        ///     Returns the duration of a buff on the player
        /// </summary>
        /// <param name="DebuffName"></param>

        public static double PlayerBuffTimeLeft(string BuffName)
        {
            double timeLeft = 0.0;

            try
            {
                timeLeft = Me.ActiveAuras[BuffName].TimeLeft.TotalSeconds;
            }
            catch
            {
                try
                {
                    WoWAura buff = Me.GetAuraByName(BuffName);
                    timeLeft = buff.TimeLeft.TotalSeconds;
                }
                catch {
                    timeLeft = GetAuraTimeLeft(Me, BuffName, false).TotalSeconds;
                }
            }


            return timeLeft;//;
        }

        public static double PlayerBuffTimeLeft(int BuffID)
        {
            double timeLeft = 0.0;

            WoWAura buff = Me.GetAuraById(BuffID);
            if(buff!=null)
                timeLeft = buff.TimeLeft.TotalSeconds;

            return timeLeft;//;
        }


        public static TimeSpan GetAuraTimeLeft(WoWUnit onUnit, string auraName, bool fromMyAura)
        {
            WoWAura wantedAura =
                onUnit.GetAllAuras().Where(a => a.Name == auraName && (!fromMyAura || a.CreatorGuid == Me.Guid)).FirstOrDefault();

            return wantedAura != null ? wantedAura.TimeLeft : TimeSpan.Zero;
        }

        /// <summary>
        ///     Check if target has specified debuff using Lua, and returns the time remaining on the debuff.
        ///     
        ///     Modified by LuckyKitten.
        /// </summary>
        /// <param name="DebuffName"></param>

        public static double TargetDebuffTimeLeft(string DebuffName, bool PlayerOnly)
        {
            return double.Parse(Lua.GetReturnValues(string.Format("local expirationTime = select(7, UnitDebuff(\"target\", \"{0}\", nil, {1})); " +
                "if expirationTime == nil then return 0 else return expirationTime - GetTime() end", DebuffName, PlayerOnly ? "\"player\"": "nil"))[0]);
        }

        /// <summary>
        ///     Gets the cooldown of specified spell using Lua
        /// </summary>
        /// <param name="SpellName">Specified Spell</param>
        /// <returns>Spell cooldown</returns>

        public static double SpellCooldown(string SpellName)
        {
            //return double.Parse(Lua.GetReturnValues(string.Format("local start, duration = GetSpellCooldown(\"{0}\"); " +
            //                                   "return (start+duration) - GetTime()", SpellName))[0]);

            double secs = SpellManager.Spells[SpellName].CooldownTimeLeft.TotalSeconds;
            //Logging.DebugOnly(SpellName+" : "+secs);

            return secs;
        }

        /// <summary>
        ///     Check if player's target is a boss using Lua.
        /// </summary>

        public static bool IsTargetBoss()
        {
            string UnitClassification = Lua.GetReturnValues("local classification = UnitClassification(\"target\"); return classification")[0];

            if (!Me.GroupInfo.IsInRaid)
            {
                if (UnitClassification == "worldboss" || (Me.CurrentTarget.Level == 87 && Me.CurrentTarget.Elite))
                    return true;

                else return false;
            }
            else
            {
                if (UnitClassification == "worldboss")
                    return true;

                else return false;
            }
        }


        /// <summary>
        ///     Targets the lowest threat unit.
        /// </summary>

        public static void TargetLowestThreat()
        {
        }

        /// <summary>
        ///     Returns true if a spell is not on cooldown or if
        ///     there is 0.3 or less left on GCD, AND the spell is known
        /// </summary>

        private static bool CanCastSpell(string SpellName)
        {
            return (SpellManager.HasSpell(SpellName) && SpellCooldown(SpellName) <= 0.3 && SpellManager.GlobalCooldownLeft.TotalSeconds < 0.2);
        }

        #endregion

        #region BT Helpers

        #region Cast Spells

        /// <summary>
        ///     Checks if specified spell is castable, if so casts it and writes to log.
        ///     Casts with Lua to make use of the ability queue.
        /// </summary>
        /// <param name="SpellName">Spell name</param>
        /// <returns></returns>

        public static Composite CastSpell(string SpellName)
        {
            return new Decorator(ret => CanCastSpell(SpellName),
                new Action(delegate {
                    if (SpellManager.Cast(SpellName))
                    {
                        Logging.Write("[{0}] {1}", CurrentHolyPower(), SpellName);
                        return RunStatus.Success;
                    }
                    return RunStatus.Failure;
                })
            );
        }

        public static Composite CastSpell(string SpellName, WoWUnit target)
        {
            return new Decorator(ret => CanCastSpell(SpellName),
                new Action(delegate
                {
                    if(SpellManager.Cast(SpellName, target))
                    {
                        Logging.Write("[{0}] {1}", CurrentHolyPower(), SpellName);
                            return RunStatus.Success;
                    }
                    return RunStatus.Failure;
                })
            );
        }

        public static int CurrentHolyPower()
        {
            //string luaReturn = Lua.GetReturnValues("local myHolyPower = UnitPower(\"player\", 9); return myHolyPower")[0];
            //return luaReturn.ToInt32();
            return (int)Me.CurrentHolyPower;
        }

        /// <summary>
        ///     Checks if specified spell is castable, if so casts it and writes to log.
        ///     Uses specified conditions.
        ///     Casts with Lua to make use of the ability queue.
        /// </summary>
        /// <param name="SpellName">Spell name</param>
        /// <param name="Conditions">Specified conditions</param>
        /// <returns></returns>

        public static Composite CastSpell(string SpellName, CanRunDecoratorDelegate Conditions)
        {
            return new Decorator(ret => Conditions(ret) && CanCastSpell(SpellName),
                new Action(delegate {
                    //Lua.DoString(String.Format("CastSpellByName(\"{0}\");", SpellName));
                    if(SpellManager.Cast(SpellName))
                     {
                        Logging.Write("[{0}] {1}", CurrentHolyPower(), SpellName);
                        return RunStatus.Success;
                    }
                    return RunStatus.Failure;
                })
            );
        }

        public static Composite CastSpell(string SpellName, WoWUnit target, CanRunDecoratorDelegate Conditions)
        {
            return new Decorator(ret => Conditions(ret) && CanCastSpell(SpellName),
                new Action(delegate
            {
                //Lua.DoString(String.Format("CastSpellByName(\"{0}\");", SpellName));
                if(SpellManager.Cast(SpellName, target))
                     {
                        Logging.Write("[{0}] {1}", CurrentHolyPower(), SpellName);
                        return RunStatus.Success;
                    }
                    return RunStatus.Failure;
                })
            );
        }

        public static Composite CastSpellButFail(string SpellName, WoWUnit target, CanRunDecoratorDelegate Conditions)
        {
            return new Decorator(ret => Conditions(ret) && CanCastSpell(SpellName),
                new Action(delegate
                {
                    //Lua.DoString(String.Format("CastSpellByName(\"{0}\");", SpellName));
                    if (SpellManager.Cast(SpellName, target))
                    {
                        Logging.Write("[{0}] {1}", CurrentHolyPower(), SpellName);
                    }
                    return RunStatus.Failure;
                })
            );
        }

        public static Composite CastSpellButFail(string SpellName, CanRunDecoratorDelegate Conditions)
        {
            return new Decorator(ret => Conditions(ret) && CanCastSpell(SpellName),
                new Action(delegate
                {
                    //Lua.DoString(String.Format("CastSpellByName(\"{0}\");", SpellName));
                    if (SpellManager.Cast(SpellName))
                    {
                        Logging.Write("[{0}] {1}", CurrentHolyPower(), SpellName);
                    }
                    return RunStatus.Failure;
                })
            );
        }

        #endregion

        #region Cast Buffs

        /// <summary>
        ///     Checks if specified buff is castable, if so casts it and writes to log.
        ///     Casts with Lua to make use of the ability queue.
        /// </summary>
        /// <param name="BuffName">Buff name</param>
        /// <returns></returns>

        public static Composite CastBuff(string BuffName)
        {
            return new Decorator(ret => CanCastSpell(BuffName),
                new Action(delegate {
                    Lua.DoString(String.Format("CastSpellByName(\"{0}\");", BuffName));
                    Logging.Write(BuffName); })
            );
        }

        /// <summary>
        ///     Checks if specified buff is castable, if so casts it and writes to log.
        ///     Uses specified conditions.
        ///     Casts with Lua to make use of the ability queue.
        /// </summary>
        /// <param name="BuffName">Buff name</param>
        /// <param name="Conditions">Specified conditions</param>
        /// <returns></returns>

        public static Composite CastBuff(string BuffName, CanRunDecoratorDelegate Conditions)
        {
            return new Decorator(ret => Conditions(ret) && CanCastSpell(BuffName),
                new Action(delegate {
                    Lua.DoString(String.Format("CastSpellByName(\"{0}\");", BuffName));
                    Logging.Write(BuffName); })
            );
        }

        #endregion

        #region Cast Cooldowns

        /// <summary>
        ///     Checks if specified cooldown is castable, if so casts it and writes to log.
        ///     Casts with Lua to make use of the ability queue.
        /// </summary>
        /// <param name="SpellName">Cooldown name</param>
        /// <returns></returns>

        public static Composite CastCooldown(string CooldownName)
        {
            return new Decorator(ret => CanCastSpell(CooldownName),
                new Action(delegate {
                    Lua.DoString(String.Format("CastSpellByName(\"{0}\");", CooldownName));
                    Logging.Write(CooldownName);
                    //return RunStatus.Failure;
                })
            );
        }

        /// <summary>
        ///     Checks if specified cooldown is castable, if so casts it and writes to log.
        ///     Uses specified conditions.
        ///     Casts with Lua to make use of the ability queue.
        /// </summary>
        /// <param name="SpellName">Cooldown name</param>
        /// <param name="Conditions">Specified conditions</param>
        /// <returns></returns>

        public static Composite CastCooldown(string CooldownName, CanRunDecoratorDelegate Conditions)
        {
            return new Decorator(ret => Conditions(ret) && CanCastSpell(CooldownName),
                new Action(delegate {
                    Lua.DoString(String.Format("CastSpellByName(\"{0}\");", CooldownName));
                    Logging.Write(CooldownName);
                    //return RunStatus.Failure;
                })
            );
        }

        #endregion

        #region Cast Heals

        /// <summary>
        ///     Checks if specified heal or protective cooldown is castable, if so casts it and writes to log.
        ///     Casts with Lua to make use of the ability queue.
        /// </summary>
        /// <param name="SpellName">Heal name</param>
        /// <returns></returns>

        public static Composite CastHealOrProtect(string HealName)
        {
            return new Decorator(ret => CanCastSpell(HealName),
                new Action(delegate {
                    Lua.DoString(String.Format("CastSpellByName(\"{0}\");", HealName));
                    Logging.Write("[" + Me.HealthPercent + "] " + HealName); })
            );
        }

        /// <summary>
        ///     Checks if specified heal or protective cooldown is castable, if so casts it and writes to log.
        ///     Uses specified conditions.
        ///     Casts with Lua to make use of the ability queue.
        /// </summary>
        /// <param name="SpellName">Heal name</param>
        /// <param name="Conditions">Specified conditions</param>
        /// <returns></returns>

        public static Composite CastHealOrProtect(string HealName, CanRunDecoratorDelegate Conditions)
        {
            return new Decorator(ret => Conditions(ret) && CanCastSpell(HealName),
                new Action(delegate {
                    Lua.DoString(String.Format("CastSpellByName(\"{0}\");", HealName));
                    Logging.Write("[" + Me.HealthPercent + "] " + HealName); })
            );
        }

        #endregion

        /// <summary>
        ///     Checks if player is auto-attacking, and if not toggles auto-attack.
        /// </summary>
        /// <returns></returns>

        public static Composite AutoAttack()
        {
            return new Decorator(ret => !Me.IsAutoAttacking,
                new Action(delegate
            {
                Me.ToggleAttack();
                Logging.Write("Auto-attack");
            })
            );
        }

        #endregion

        #endregion

        #region Lucky's Helpers

        public static bool HasTalent(string talent)
        {
            

            return false;
        }

        public static int PlayerHasBuffStacks(string BuffName)
        {
            int stacks = 0;
            try{
                stacks = (int)Me.ActiveAuras[BuffName].StackCount;
            }catch{
                stacks = 0;
            }
            return stacks;
        }

        #region Interupt Spell Code

        public static string ClassInteruptSpell
        {
            get {
                string spell = "Rebuke";
                /*switch (Me.Class){
                case WoWClass.Paladin : spell = "Rebuke"; break;
                }*/
                return spell;
            }
        }

        public static Composite CheckForInterupts()
        {
            

            return new Action(delegate {

                String[] InteruptSpells = Crusader.Settings.Instance.InteruptSpellList;

                IEnumerable<WoWUnit> castingUnits = NearbyUnfriendlyUnits.Where(u => u.IsCasting && u.CanInterruptCurrentSpellCast && u.Distance < 8);

                WoWUnit toInterupt = null;

                foreach (WoWUnit c in castingUnits)
                {
                    WoWSpell spell = c.CastingSpell;
                    
                    if (spell != null && InteruptSpells.Contains(spell.Name))
                    {
                        toInterupt = c;
                    }
                }

                if (toInterupt != null && CanCastSpell(ClassInteruptSpell))
                {
                    Logging.Write("{0} is casting {1}, attempt to interrupt.", toInterupt.Name, toInterupt.Name);
                    SpellManager.Cast(ClassInteruptSpell, toInterupt);
                }

                return RunStatus.Failure;
            
            });
        }

        #endregion

        #region Trinkets and Items

        #region Glyphs

        public static HashSet<string> Glyphs = new HashSet<string>();

        public static void PopulateGlyphs()
        {
            Glyphs.Clear();

            var glyphCount = Lua.GetReturnVal<int>("return GetNumGlyphSockets()", 0);

            if (glyphCount != 0)
            {
                for (int i = 1; i <= glyphCount; i++)
                {
                    List<string> glyphInfo = Lua.GetReturnValues(String.Format("return GetGlyphSocketInfo({0})", i));

                    if (glyphInfo != null && glyphInfo[3] != "nil" && !string.IsNullOrEmpty(glyphInfo[3]))
                    {
                        Glyphs.Add(WoWSpell.FromId(int.Parse(glyphInfo[3])).Name.Replace("Glyph of ", ""));
                    }
                }
            }
        }

        public static bool PlayerHasGlyph(string glyph)
        {
            if (Glyphs.Count <= 0)
                PopulateGlyphs();
            return Glyphs.Contains(glyph);
        }

        #endregion


        public static Composite StopRotation()
        {
            return new Action(delegate {
                if (Crusader.Settings.Instance.DisableRotation)
                    return RunStatus.Success;
                else return RunStatus.Failure;
            });
        }

        public static IEnumerable<WoWUnit> NearbyLightwells
        {
            get {
                uint wellID = 31897;
                return ObjectManager.GetObjectsOfType<WoWUnit>(false, false).Where(p => p.Entry==wellID &&p.DistanceSqr <= 40 * 40).ToList(); }
        }

        public static Composite UseLightwell(int HealthPercent)
        {
            return new Action(delegate
            {
                if (Me.HealthPercent <= HealthPercent && PlayerBuffTimeLeft("Lightwell Renew") <= 0)
                {
                    foreach (WoWUnit gunit in NearbyLightwells)
                    {
                        if (gunit.Distance < 20)
                        {
                            gunit.Interact();
                            Logging.Write("Used lightwell");
                            break;
                        }
                    }
                }

                return RunStatus.Failure;
            });
        }

        public static Composite UseLightwell()
        {
            return UseLightwell(Crusader.Settings.Instance.HealthLightwell);
        }


        public static Composite UseHealthstone()
        {
            //NYI
            return new Action(delegate { return RunStatus.Failure; });
        }

        public static Composite UseTrinket1(string cooldown)
        {

            return UseItemOnCooldown(EquippedItems[InventorySlot.Trinket0Slot], Settings.Instance.UseTrinket1, cooldown);
        }

        public static Composite UseTrinket2(string cooldown)
        {

            return UseItemOnCooldown(EquippedItems[InventorySlot.Trinket1Slot], Settings.Instance.UseTrinket2, cooldown);
        }

        public static Composite UseGloves(string cooldown)
        {

            return UseItemOnCooldown(EquippedItems[InventorySlot.HandsSlot], Settings.Instance.UseGloves, cooldown);
        }

        public static Composite UseItemOnCooldown(WoWItem item, Settings.CD cd, string cooldown)
        {
            return new PrioritySelector(
                new Decorator(ret => cd == Settings.CD.OnCooldown,
                    UseItem(item)
                ),
                
                new Decorator(ret => cd == Settings.CD.LowHealth && Me.HealthPercent < 45,
                    UseItem(item)
                ),

                new Decorator(ret => cd == Settings.CD.DuringCoolDown && (PlayerHasBuff(cooldown) || SpellCooldown(cooldown) > 55 || !Crusader.Settings.Instance.UseCooldowns),
                    UseItem(item)
                ));
        }

        private static Composite UseItem(WoWItem item){

            return new Action(delegate
            {
                 if (item != null && item.Usable && item.Cooldown <= 0)
                {
                    Logging.Write("Using " + item.Name);

                    item.Use();
                }

            }
            );
        }

        public static Composite ValidUnitCheck()
        {
            return new Action(delegate {
                return ValidUnit(Me.CurrentTarget) ? RunStatus.Failure : RunStatus.Success ;
            });
        }

        public static Dictionary<InventorySlot, WoWItem> EquippedItems
        {
            get
            {
                var equipped = new Dictionary<InventorySlot, WoWItem>();
                ObjectManager.Update();


                WoWItem[] items = Me.Inventory.Equipped.Items;

                equipped.Clear();
                for (int i = 0; i < 23; i++)
                    equipped.Add((InventorySlot)(i + 1), items[i]);

                return equipped;
            }
        }

        #endregion
        #endregion

    }
}